home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / unix / volume11 / watcher / part01 next >
Encoding:
Internet Message Format  |  1987-09-27  |  58.3 KB

  1. Subject:  v11i082:  Watcher system monitor program, Part01/02
  2. Newsgroups: comp.sources.unix
  3. Sender: sources
  4. Approved: rs@uunet.UU.NET
  5.  
  6. Submitted-by: Kenneth Ingham <ingham@charon.unm.edu>
  7. Posting-number: Volume 11, Issue 82
  8. Archive-name: watcher/part01
  9.  
  10. [  Watcher is a system-monitor utililty, described at the Phoenix
  11.    Usenix.  --r$  ]
  12.  
  13. #! /bin/sh
  14. # This is a shell archive.  Remove anything before this line, then unpack
  15. # it by saving it into a file and typing "sh file".  To overwrite existing
  16. # files, type "sh file -c".  You can also feed this as standard input via
  17. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  18. # will see the following message at the end:
  19. #        "End of archive 1 (of 2)."
  20. # Contents:  Docs Docs/Abstract Docs/Makefile Docs/README Docs/macros
  21. #   Ideas MANIFEST Makefile README Support Support/Daemons
  22. #   Support/README Support/UnmHosts Support/Watcherfile
  23. #   Support/crontab.entry Support/syswatch baderr.c check_item.c
  24. #   checkline.c clean_hist.c do_args.c doit.c externs.c find_of.c
  25. #   find_pre_cmd.c find_pre_val.c get_col_fld.c get_rel_fld.c
  26. #   getargv.c init.c init_sigs.c line_to_vec.c main.c open_cf.c
  27. #   open_hf.c pp.c pp_change.c pp_out.c read_hist.c save_key.c
  28. #   yyerror.c yylex.c
  29. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  30. if test ! -d Docs ; then
  31.     echo shar: Creating directory \"Docs\"
  32.     mkdir Docs
  33. fi
  34. if test -f Docs/Abstract -a "${1}" != "-c" ; then 
  35.   echo shar: Will not over-write existing file \"Docs/Abstract\"
  36. else
  37. echo shar: Extracting \"Docs/Abstract\" \(3638 characters\)
  38. sed "s/^X//" >Docs/Abstract <<'END_OF_Docs/Abstract'
  39. X.sp 0.5i
  40. X.ce 2
  41. XKeeping watch over the flocks
  42. Xat night (and day)
  43. X.sp 0.3i
  44. X.ce 8
  45. XKenneth Ingham
  46. XUniversity of New Mexico Computing Center
  47. XDistributed Systems Group
  48. X2701 Campus NE
  49. XAlbuquerque, NM 87131
  50. X(505) 277-8044
  51. Xingham@charon.unm.edu
  52. Xucbvax!unmvax!charon!ingham
  53. X.sp 0.2i
  54. X.ce
  55. XTopic Areas: Applications, System management, Utilities
  56. X.sp 0.5i
  57. XThe computing facilities offered by the University of New Mexico
  58. XComputing Center include three microvaxen, five large vaxen (780 or
  59. Xbigger), and a Sequent B8000.  In addition to these Unix/VMS machines,
  60. Xthe UNMCC Distributed Systems Group (DSG) monitors a number of the
  61. Xvarious microvaxen and sun workstations scattered across campus.  This
  62. Xduty falls to the DSG Programmer designated as "DOC", or "DSG On Call",
  63. Xwho receives his beeper based on a monthly rotation schedule.
  64. X.sp
  65. XIn the past, shell scripts running every six hours reported various
  66. Xsystem statistics to DOC, who then scanned the output for signs of
  67. Xpossible trouble.  As the number of machines and the number of
  68. Xpotential problems grew, the mound of output that DOC had to process,
  69. Xmost of which merely indicated normal system operation, became
  70. Xoverwhelming.  Now, with several machines to monitor and only one
  71. Xperson acting in this capacity, DOC can often waste a tremendous amount
  72. Xof time wading through system status reports, time which can be better
  73. Xspent actually fixing system problems.
  74. X.sp
  75. XIn response to this situation, the author developed a tool which 
  76. Xintroduces some intelligence into the machine's self-reporting, letting
  77. Xthe machine filter out messages indicating normal operation and
  78. Xforwarding to DOC only those messages which point out trouble areas.
  79. XThe result of these efforts is Watcher, a very general and extensible
  80. Xsystem self-monitor.  Running more often than the set of
  81. Xshell scripts, Watcher keeps closer tabs on the system; since it
  82. Xdelivers only a summary of potential problems, however, this extra
  83. Xmonitoring produces \fIno\fR corresponding increase in the demand on
  84. Xthe system manager.  No problems slip by unnoticed in the more concise
  85. Xoutput, leading to an improvement in overall system availability as well
  86. Xas the more effective utilization of the system manager's time.
  87. X.sp
  88. XWatcher was designed to be almost as flexible as DOC in deciding what
  89. Xconstitutes a problem with the system.  Running at intervals specified
  90. Xin crontab, Watcher issues a number of
  91. Xuser-specified commands (each of which
  92. Xdelivers its output in a different format), parsing all or part of the
  93. Xoutput from either the left or the right.  It compares this 
  94. Xto the last such output obtained, checking for indications 
  95. Xof a system abnormality.  Such signs might take the form of a
  96. Xtoo abrupt change in a certain value (e.g. a process which suddenly
  97. Xbegins gobbling vast amounts of cpu time),
  98. Xa value which exceeds the allowable maximum or minimum (such as a
  99. Xan overly-full file system),
  100. Xor an unacceptable change in a string value
  101. X(e.g. when "up" changes to "down").  For commands such as
  102. X"ps" whose output varies considerably with each run, specific 
  103. Xparts of the output can be designated as a key; successive runs of
  104. XWatcher will home in on these key areas for their comparisons.
  105. X.sp
  106. XSince the user specifies not only the commands Watcher will execute and
  107. Xthe time lapse between successive runs, but also the aforementioned
  108. Xparameters which indicate system anomalies, Watcher can easily be seen
  109. Xas a very flexible, general system monitor.  Its use at UNM has provided
  110. Xa marked increase in the productivity of the system manager, which has
  111. Xled in turn to the increase in the reliability and availability of the
  112. Xsystems at UNMCC.
  113. END_OF_Docs/Abstract
  114. if test 3638 -ne `wc -c <Docs/Abstract`; then
  115.     echo shar: \"Docs/Abstract\" unpacked with wrong size!
  116. fi
  117. # end of overwriting check
  118. fi
  119. if test -f Docs/Makefile -a "${1}" != "-c" ; then 
  120.   echo shar: Will not over-write existing file \"Docs/Makefile\"
  121. else
  122. echo shar: Extracting \"Docs/Makefile\" \(73 characters\)
  123. sed "s/^X//" >Docs/Makefile <<'END_OF_Docs/Makefile'
  124. XTROFF=xroff
  125. X
  126. Xpaper:
  127. X    $(TROFF) macros Paper
  128. X
  129. Xabstract:
  130. X    $(TROFF) Abstract
  131. END_OF_Docs/Makefile
  132. if test 73 -ne `wc -c <Docs/Makefile`; then
  133.     echo shar: \"Docs/Makefile\" unpacked with wrong size!
  134. fi
  135. # end of overwriting check
  136. fi
  137. if test -f Docs/README -a "${1}" != "-c" ; then 
  138.   echo shar: Will not over-write existing file \"Docs/README\"
  139. else
  140. echo shar: Extracting \"Docs/README\" \(315 characters\)
  141. sed "s/^X//" >Docs/README <<'END_OF_Docs/README'
  142. XIn this directory is all of the documenttion about watcher.  It should
  143. Xinclude a man page, the abstract sent in to usenix, and the paper
  144. Xpublished in the proceedings of the 1987 Summer Usenix in Phoenix.
  145. X
  146. XThe Makefile shows how to print the abstract and the paper.  The man
  147. Xpage is the same as all other man pages.
  148. END_OF_Docs/README
  149. if test 315 -ne `wc -c <Docs/README`; then
  150.     echo shar: \"Docs/README\" unpacked with wrong size!
  151. fi
  152. # end of overwriting check
  153. fi
  154. if test -f Docs/macros -a "${1}" != "-c" ; then 
  155.   echo shar: Will not over-write existing file \"Docs/macros\"
  156. else
  157. echo shar: Extracting \"Docs/macros\" \(712 characters\)
  158. sed "s/^X//" >Docs/macros <<'END_OF_Docs/macros'
  159. X\" macro definitions
  160. X.de EX
  161. X.nf
  162. X.in +0.25i
  163. X.sp
  164. X..
  165. X.de NX
  166. X.in -0.25i
  167. X.fi
  168. X.ad
  169. X.sp
  170. X..
  171. X.de SE
  172. X.ps \\n(ps+1
  173. X.ft B
  174. X.sp 0.2i
  175. X\\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
  176. X.ft
  177. X.ps \\n(ps
  178. X.sp 0.2i
  179. X..
  180. X.de NP
  181. X'sp 0.75i
  182. X.tl ''%''
  183. X'bp
  184. X'sp 1.0i
  185. X..
  186. X.de TI
  187. X.ps \\n(ps+5
  188. X.vs \\n(vs+5
  189. X.ft B
  190. X.ce
  191. X\\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
  192. X.ps \\n(ps
  193. X.vs \\n(vs
  194. X.ft
  195. X..
  196. X.de AU
  197. X.sp 0.5i
  198. X.ps \\n(ps+3
  199. X.ft I
  200. X.ce \\$1 
  201. X.ps \\n(ps
  202. X..
  203. X.de AB
  204. X.ll -0.5i
  205. X.in +0.5i
  206. X.sp 0.2i
  207. X.ps \\n(ps+3
  208. X.ft B
  209. X.ce
  210. XAbstract
  211. X.ps \\n(ps
  212. X.sp 0.2i
  213. X.ft R
  214. X..
  215. X.de BD
  216. X.in -0.5i
  217. X.ll +0.5i
  218. X.sp 0.3i
  219. X.ps \\n(ps
  220. X.ft R
  221. X..
  222. X\" end of macro definitions
  223. X.wh -1.5i NP
  224. X.in 0.25i
  225. X.ll 6.25i
  226. X.sp 0.5i \" for the first page
  227. X.ps 11
  228. X.vs 14
  229. X.nr ps 11
  230. X.nr vs 14
  231. X\" end of macro package
  232. END_OF_Docs/macros
  233. if test 712 -ne `wc -c <Docs/macros`; then
  234.     echo shar: \"Docs/macros\" unpacked with wrong size!
  235. fi
  236. # end of overwriting check
  237. fi
  238. if test -f Ideas -a "${1}" != "-c" ; then 
  239.   echo shar: Will not over-write existing file \"Ideas\"
  240. else
  241. echo shar: Extracting \"Ideas\" \(1347 characters\)
  242. sed "s/^X//" >Ideas <<'END_OF_Ideas'
  243. X    Repace number with int or float.  Currently watcher treats all
  244. X        numbers as floats.  There is some code already there
  245. X        that could handle the different types.  The %d for a
  246. X        float is counterintuitive.  This would be fixed by
  247. X        making %d int and %f float like printf.
  248. X
  249. X    Use yacc's union rather than YYSTYPE default.  This would
  250. X        probably help portability.
  251. X
  252. X    Print alias in pp output.  Currently it isn't printed.  No real
  253. X        reason for this.
  254. X
  255. X    Multiple ok values for string fields.  Sometimes there may be
  256. X        more than one string value which is considered "ok".
  257. X        Watcher should be able to handle this.  Possible
  258. X        syntax:
  259. X
  260. X(/usr/ucb/ruptime | fgrep -f /usr/local/lib/watcher/UnmHosts) { ruptime }
  261. X    2 status%s 1 machine%k 7 loadav%d:
  262. X        loadav 0 10;
  263. X        status "up", "slow", "dead".
  264. X
  265. X    Positive and/or negative deltas make a difference.  Currently
  266. X        watcher only notices things which increase.  It would
  267. X        probably be useful to watch for things that drop also.
  268. X        Possible syntax:
  269. X
  270. X(df -i | /usr/ucb/tail +2 | grep -v tmp) { 'df no tmp' }
  271. X    1-9 filesystem%k 41-42 spaceused%d 64-65 inodesused%d 1-9 device%k:
  272. X        spaceused -15%;
  273. X        spaceused 0 89;
  274. X
  275. X    Right to left parsing as option instead of always l-r.  It may
  276. X        be easier at times to specify that the useful info is
  277. X        located in the fifth from the right column rather than
  278. X        the eit`ghth from the left.
  279. END_OF_Ideas
  280. if test 1347 -ne `wc -c <Ideas`; then
  281.     echo shar: \"Ideas\" unpacked with wrong size!
  282. fi
  283. # end of overwriting check
  284. fi
  285. if test -f MANIFEST -a "${1}" != "-c" ; then 
  286.   echo shar: Will not over-write existing file \"MANIFEST\"
  287. else
  288. echo shar: Extracting \"MANIFEST\" \(1494 characters\)
  289. sed "s/^X//" >MANIFEST <<'END_OF_MANIFEST'
  290. X   File Name        Archive #    Description
  291. X-----------------------------------------------------------
  292. X Docs                      1    
  293. X Docs/Abstract             1    
  294. X Docs/Makefile             1    
  295. X Docs/Paper                2    
  296. X Docs/README               1    
  297. X Docs/macros               1    
  298. X Docs/watcher.1            2    
  299. X Ideas                     1    
  300. X MANIFEST                  1    This shipping list
  301. X Makefile                  1    
  302. X README                    1    
  303. X Support                   1    
  304. X Support/Daemons           1    
  305. X Support/README            1    
  306. X Support/UnmHosts          1    
  307. X Support/Watcherfile       1    
  308. X Support/crontab.entry     1    
  309. X Support/syswatch          1    
  310. X baderr.c                  1    
  311. X check_item.c              1    
  312. X checkline.c               1    
  313. X clean_hist.c              1    
  314. X control.y                 2    
  315. X defs.h                    2    
  316. X do_args.c                 1    
  317. X doit.c                    1    
  318. X externs.c                 1    
  319. X find_of.c                 1    
  320. X find_pre_cmd.c            1    
  321. X find_pre_val.c            1    
  322. X get_col_fld.c             1    
  323. X get_rel_fld.c             1    
  324. X getargv.c                 1    
  325. X init.c                    1    
  326. X init_sigs.c               1    
  327. X line_to_vec.c             1    
  328. X main.c                    1    
  329. X open_cf.c                 1    
  330. X open_hf.c                 1    
  331. X pp.c                      1    
  332. X pp_change.c               1    
  333. X pp_out.c                  1    
  334. X read_hist.c               1    
  335. X save_key.c                1    
  336. X yyerror.c                 1    
  337. X yylex.c                   1    
  338. END_OF_MANIFEST
  339. if test 1494 -ne `wc -c <MANIFEST`; then
  340.     echo shar: \"MANIFEST\" unpacked with wrong size!
  341. fi
  342. # end of overwriting check
  343. fi
  344. if test -f Makefile -a "${1}" != "-c" ; then 
  345.   echo shar: Will not over-write existing file \"Makefile\"
  346. else
  347. echo shar: Extracting \"Makefile\" \(891 characters\)
  348. sed "s/^X//" >Makefile <<'END_OF_Makefile'
  349. X#
  350. X# makefile for watcher
  351. X#
  352. X# SYS should be either BSD or SYSV
  353. XSYS = BSD
  354. X
  355. XOBJS = baderr.o check_item.o checkline.o do_args.o doit.o externs.o\
  356. X    find_of.o find_pre_cmd.o find_pre_val.o get_col_fld.o\
  357. X    get_rel_fld.o getargv.o init.o init_sigs.o line_to_vec.o main.o\
  358. X    open_cf.o open_hf.o pp.o pp_change.o pp_out.o read_hist.o\
  359. X    save_key.o y.tab.o yyerror.o yylex.o
  360. XCFLAGS = -O -D$(SYS)
  361. X
  362. XDIST = Makefile Docs Support Ideas
  363. X
  364. Xwatcher: $(OBJS)
  365. X    cc $(CFLAGS) -o watcher $(OBJS)
  366. X
  367. Xclean:
  368. X    rm -f a.out core watcher *.o y.tab.c y.tab.h y.output Make.out
  369. X
  370. Xlint:
  371. X    lint -x *.c > Lint.out
  372. X
  373. Xshar:
  374. X    shar README *.c *.h *.y $(DIST) > Watcher.shar
  375. X
  376. X# Two shar files are made because one is too large for the mailers with
  377. X# a 64K limit.
  378. Xdist:
  379. X    shar README *.c > Watcher.shar1
  380. X    shar *.h *.y $(DIST) > Watcher.shar2
  381. X
  382. Xy.tab.c y.tab.h: control.y
  383. X    yacc -d control.y
  384. X
  385. Xy.tab.o: y.tab.c
  386. Xyylex.o: y.tab.h
  387. X$(OBJS): defs.h
  388. END_OF_Makefile
  389. if test 891 -ne `wc -c <Makefile`; then
  390.     echo shar: \"Makefile\" unpacked with wrong size!
  391. fi
  392. # end of overwriting check
  393. fi
  394. if test -f README -a "${1}" != "-c" ; then 
  395.   echo shar: Will not over-write existing file \"README\"
  396. else
  397. echo shar: Extracting \"README\" \(1471 characters\)
  398. sed "s/^X//" >README <<'END_OF_README'
  399. XWatcher has been sucessfully made and run on 4.3BSD on vaxen, Ultrix 1.1
  400. X& 1.2 on vaxen (what else?), and a sun 3/160 version 3.0 of the sun os.
  401. XThanks to Alan Silverstein for bringing up watcher on a system V.2 machine 
  402. Xand pointing out the berkeleyisms (which I hope are all #ifdef'd now).
  403. X
  404. XThere have been recent problems which I cannot reproduce which appear to
  405. Xbe a pointer in a malloc'd area pointing off a bit.  I have been unable
  406. Xso far to track this problem down.
  407. X
  408. XA short description of all of the files and directories for watcher.
  409. X
  410. XIdeas - changes that I need to or would like to make for watcher.
  411. Xknown bugs are listed here.  Someday I will fix them.  If you fix them
  412. Xbefore I do, please send the fixes to me.
  413. X
  414. XDocs - here is all of the documentation for watcher.  A man page and the
  415. Xpaper that appeared in the proceedings of the summer usenix conference 
  416. Xin 1987.
  417. X
  418. XMakefile - you guessed it.
  419. X
  420. XREADME - this file
  421. X
  422. XSupport - directory of useful files to use with watcher.  There were
  423. Xtaken from actual use at UNM (although they were taken a while back and
  424. Xmay not be what is in use now).  They may help in seeing how at least
  425. Xone site is running watcher.
  426. X
  427. XThe rest of the files should be the source.
  428. X
  429. XHappy Watching.
  430. X
  431. XBug fixes and reports should be sent to:
  432. X
  433. XKenneth Ingham, UNM Computing Center, Albuquerque, NM 87131, 505-277-8044
  434. X
  435. XUsenet:   {convex,ucbvax,gatech,csu-cs,anl-mcs}!unmvax!charon!ingham
  436. XBITNET:   ingham@unmb
  437. XInternet: ingham@charon.UNM.EDU
  438. X
  439. END_OF_README
  440. if test 1471 -ne `wc -c <README`; then
  441.     echo shar: \"README\" unpacked with wrong size!
  442. fi
  443. # end of overwriting check
  444. fi
  445. if test ! -d Support ; then
  446.     echo shar: Creating directory \"Support\"
  447.     mkdir Support
  448. fi
  449. if test -f Support/Daemons -a "${1}" != "-c" ; then 
  450.   echo shar: Will not over-write existing file \"Support/Daemons\"
  451. else
  452. echo shar: Extracting \"Support/Daemons\" \(91 characters\)
  453. sed "s/^X//" >Support/Daemons <<'END_OF_Support/Daemons'
  454. Xcron
  455. Xrwhod
  456. Xrouted
  457. Xupdate
  458. Xdaemon
  459. Xinit
  460. Xstatd
  461. Xsendmail -bd
  462. Xsyslogd
  463. Xnamed
  464. Xswapper
  465. Xcensus
  466. Xinetd
  467. END_OF_Support/Daemons
  468. if test 91 -ne `wc -c <Support/Daemons`; then
  469.     echo shar: \"Support/Daemons\" unpacked with wrong size!
  470. fi
  471. # end of overwriting check
  472. fi
  473. if test -f Support/README -a "${1}" != "-c" ; then 
  474.   echo shar: Will not over-write existing file \"Support/README\"
  475. else
  476. echo shar: Extracting \"Support/README\" \(704 characters\)
  477. sed "s/^X//" >Support/README <<'END_OF_Support/README'
  478. XThese are files used at the University of New Mexico as of May 19, 1987
  479. Xor so.  Due to the evolving nature of what we determine needs to be
  480. Xwatched and the various on call people coming up with new ways to watch
  481. Xfor problems without generating more output, it is probably not what we
  482. Xare now running.  However it should give an idea of how watcher is used
  483. Xat UNM.
  484. X
  485. XThe following files all live in /usr/local/lib/watcher (besides the
  486. Xsource for watcher itself):
  487. X    Daemons
  488. X    UnmHosts
  489. X    Watcherfile
  490. X
  491. XThe following are misc. files which are also used with watcher.
  492. X    crontab.entry - what we have in our crontab
  493. X    syswatch - a shell script which actually runs watcher and mails
  494. X        the output to the on call person.
  495. END_OF_Support/README
  496. if test 704 -ne `wc -c <Support/README`; then
  497.     echo shar: \"Support/README\" unpacked with wrong size!
  498. fi
  499. # end of overwriting check
  500. fi
  501. if test -f Support/UnmHosts -a "${1}" != "-c" ; then 
  502.   echo shar: Will not over-write existing file \"Support/UnmHosts\"
  503. else
  504. echo shar: Extracting \"Support/UnmHosts\" \(50 characters\)
  505. sed "s/^X//" >Support/UnmHosts <<'END_OF_Support/UnmHosts'
  506. Xariel
  507. Xcharon
  508. Xdeimos
  509. Xeuropa
  510. Xgeinah
  511. Xhydra
  512. Xizar
  513. Xunmb
  514. END_OF_Support/UnmHosts
  515. if test 50 -ne `wc -c <Support/UnmHosts`; then
  516.     echo shar: \"Support/UnmHosts\" unpacked with wrong size!
  517. fi
  518. # end of overwriting check
  519. fi
  520. if test -f Support/Watcherfile -a "${1}" != "-c" ; then 
  521.   echo shar: Will not over-write existing file \"Support/Watcherfile\"
  522. else
  523. echo shar: Extracting \"Support/Watcherfile\" \(936 characters\)
  524. sed "s/^X//" >Support/Watcherfile <<'END_OF_Support/Watcherfile'
  525. X(df -i | /usr/ucb/tail +2 | grep -v tmp) { 'df no tmp' }
  526. X    1-9 filesystem%k 41-42 spaceused%d 64-65 inodesused%d 1-9 device%k:
  527. X        spaceused 15%;
  528. X        spaceused 0 89;
  529. X        inodesused 15%;
  530. X        inodesused 0 49.
  531. X(df -i | /usr/ucb/tail +2 | grep tmp) { 'df tmp only' }
  532. X    1-9 filesystem%k 41-42 spaceused%d 64-65 inodesused%d 1-9 device%k:
  533. X        spaceused 0 89;
  534. X        inodesused 0 49.
  535. X(/usr/ucb/ruptime | fgrep -f /usr/local/lib/watcher/UnmHosts) { ruptime }
  536. X    2 status%s 1 machine%k 7 loadav%d:
  537. X        loadav 0 10;
  538. X        status "up".
  539. X(ps -aux | fgrep -v -f /usr/local/lib/watcher/Daemons | /usr/ucb/tail +2)
  540. X  { 'ps with no daemons' }
  541. X     9-14 pid%k  16-19 percentcpu%d  42-45 cputime%d:
  542. X        cputime 0 10.
  543. X(ps -ax | fgrep -f /usr/local/lib/watcher/Daemons | uniq -c) { 'daemon count' }
  544. X    1 daemon_count%d 6 daemon_name%k:
  545. X        daemon_count 0 1.
  546. X(ps -aux | fgrep -f /usr/local/lib/watcher/Daemons ) { 'daemon ps' }
  547. X     9-14 pid%k  16-19 percentcpu%d  42-45 cputime%d:
  548. X        cputime 2.
  549. END_OF_Support/Watcherfile
  550. if test 936 -ne `wc -c <Support/Watcherfile`; then
  551.     echo shar: \"Support/Watcherfile\" unpacked with wrong size!
  552. fi
  553. # end of overwriting check
  554. fi
  555. if test -f Support/crontab.entry -a "${1}" != "-c" ; then 
  556.   echo shar: Will not over-write existing file \"Support/crontab.entry\"
  557. else
  558. echo shar: Extracting \"Support/crontab.entry\" \(804 characters\)
  559. sed "s/^X//" >Support/crontab.entry <<'END_OF_Support/crontab.entry'
  560. X0       0  *   *   * root /usr/local/lib/syswatch >> /usr/lib/cronlog
  561. X0       2  *   *   * root /usr/local/lib/syswatch >> /usr/lib/cronlog
  562. X0       4  *   *   * root /usr/local/lib/syswatch >> /usr/lib/cronlog
  563. X0       6  *   *   * root /usr/local/lib/syswatch >> /usr/lib/cronlog
  564. X0       8  *   *   * root /usr/local/lib/syswatch >> /usr/lib/cronlog
  565. X0       10 *   *   * root /usr/local/lib/syswatch >> /usr/lib/cronlog
  566. X0       12 *   *   * root /usr/local/lib/syswatch >> /usr/lib/cronlog
  567. X0       14 *   *   * root /usr/local/lib/syswatch >> /usr/lib/cronlog
  568. X0       16 *   *   * root /usr/local/lib/syswatch >> /usr/lib/cronlog
  569. X0       18 *   *   * root /usr/local/lib/syswatch >> /usr/lib/cronlog
  570. X0       20 *   *   * root /usr/local/lib/syswatch >> /usr/lib/cronlog
  571. X0       22 *   *   * root /usr/local/lib/syswatch >> /usr/lib/cronlog
  572. END_OF_Support/crontab.entry
  573. if test 804 -ne `wc -c <Support/crontab.entry`; then
  574.     echo shar: \"Support/crontab.entry\" unpacked with wrong size!
  575. fi
  576. # end of overwriting check
  577. fi
  578. if test -f Support/syswatch -a "${1}" != "-c" ; then 
  579.   echo shar: Will not over-write existing file \"Support/syswatch\"
  580. else
  581. echo shar: Extracting \"Support/syswatch\" \(286 characters\)
  582. sed "s/^X//" >Support/syswatch <<'END_OF_Support/syswatch'
  583. X#! /bin/csh -f
  584. Xset FILE = /tmp/watch$$
  585. Xset MAILTO = ( doc )
  586. Xcd /usr/local/lib/watcher
  587. Xwatcher > $FILE
  588. Xif (-z $FILE) then
  589. X    echo " " | mail -s "`hostname` had no problems at `date`" $MAILTO
  590. Xelse
  591. X    mail -s "System problem report for `hostname` at `date`" $MAILTO < $FILE
  592. Xendif
  593. X
  594. Xrm -f $FILE
  595. END_OF_Support/syswatch
  596. if test 286 -ne `wc -c <Support/syswatch`; then
  597.     echo shar: \"Support/syswatch\" unpacked with wrong size!
  598. fi
  599. chmod +x Support/syswatch
  600. # end of overwriting check
  601. fi
  602. if test -f baderr.c -a "${1}" != "-c" ; then 
  603.   echo shar: Will not over-write existing file \"baderr.c\"
  604. else
  605. echo shar: Extracting \"baderr.c\" \(853 characters\)
  606. sed "s/^X//" >baderr.c <<'END_OF_baderr.c'
  607. X/* 
  608. X   baderr: A bad error has been caught.  Print an error message explaining
  609. X    why we are dying, then exit.
  610. X
  611. X   Assumptions:
  612. X    the signal number in sig is an actual signal number and has an
  613. X    entry in sys_siglist (BSD ONLY).
  614. X
  615. X   Arguments:
  616. X    sig: the number of the signal which brought us here.
  617. X
  618. X   Author:
  619. X    Kenneth Ingham
  620. X
  621. X   Copyright (C) 1987 The University of New Mexico
  622. X*/
  623. X
  624. X#include "defs.h"
  625. X
  626. Xbaderr(sig)
  627. Xint sig;
  628. X{
  629. X    extern char *sys_siglist[];
  630. X
  631. X    printf("                                            \n");
  632. X    printf("                                            \n");
  633. X#ifdef BSD
  634. X    printf(">> Unrecoverable error.  %s  Bye. <<\n",sys_siglist[sig]);
  635. X#else
  636. X    printf(">> Unrecoverable error.  Signal %d.  Bye. <<\n", sig);
  637. X#endif
  638. X    printf("                                            \n");
  639. X    printf("                                            \n");
  640. X    exit(1);
  641. X}
  642. END_OF_baderr.c
  643. if test 853 -ne `wc -c <baderr.c`; then
  644.     echo shar: \"baderr.c\" unpacked with wrong size!
  645. fi
  646. # end of overwriting check
  647. fi
  648. if test -f check_item.c -a "${1}" != "-c" ; then 
  649.   echo shar: Will not over-write existing file \"check_item.c\"
  650. else
  651. echo shar: Extracting \"check_item.c\" \(2976 characters\)
  652. sed "s/^X//" >check_item.c <<'END_OF_check_item.c'
  653. X/*
  654. X   check_item: given a value and a change format structure, make sure
  655. X   that the value is in range.
  656. X
  657. X   Basically, this routine is a large switch statement on the type of
  658. X   change that grabs the necessary info, and checks to see if the item
  659. X   is worth mentioning.
  660. X
  661. X   Note that what we print out depends on whether or not something else
  662. X   has been found wrong on this line.
  663. X
  664. X   Kenneth Ingham
  665. X
  666. X   Copyright (C) 1987 The University of New Mexico
  667. X*/
  668. X
  669. X#include "defs.h"
  670. X
  671. Xcheck_item(cf, value, cmd, line, prev_val)
  672. Xchar *value, *cmd, *line;
  673. Xstruct change_fmt_st *cf;
  674. Xunion all_u *prev_val;
  675. X{
  676. X    extern int line_ok, cmd_ok;
  677. X    double v, pct_chg, abs_chg;
  678. X    int len;
  679. X
  680. X    v = atof(value);
  681. X    len = strlen(value);
  682. X
  683. X    switch(cf->type) {
  684. X        case PERCENT:
  685. X            if (prev_val == NULL) /* nothing to compare with */
  686. X                return;
  687. X            if (v == 0) /* avoid divide by 0 */
  688. X                return;
  689. X            pct_chg = (v - prev_val->floatval) / v;
  690. X            if (pct_chg > cf->fmt.percent) {
  691. X                if (line_ok) {
  692. X                    printf("%s had ", cmd);
  693. X                    printf("%s change by more than %.2f percent.\n",
  694. X                        cf->name, cf->fmt.percent*100);
  695. X                    printf("%s\n",line);
  696. X                }
  697. X                else {
  698. X                    printf("Also, it had ");
  699. X                    printf("%s change by more than %.2f percent.\n",
  700. X                        cf->name, cf->fmt.percent*100);
  701. X                }
  702. X                printf("Previous value %.2f; ",
  703. X                    prev_val->floatval);
  704. X                printf("current value %.2f.\n", v);
  705. X                line_ok = False;
  706. X            }
  707. X            break;
  708. X        case ABSOLUTE:
  709. X            if (prev_val == NULL) /* nothing to compare with */
  710. X                return;
  711. X            abs_chg = v - prev_val->floatval;
  712. X            if (abs_chg > cf->fmt.abs_amount) {
  713. X                if (line_ok) {
  714. X                    printf("%s had ", cmd);
  715. X                    printf("%s change by more than %.2f.\n",
  716. X                        cf->name, cf->fmt.abs_amount);
  717. X                    printf("%s\n",line);
  718. X                }
  719. X                else {
  720. X                    printf("Also, it had ");
  721. X                    printf("%s change by more than %.2f.\n",
  722. X                        cf->name, cf->fmt.abs_amount);
  723. X                }
  724. X                printf("Previous value %.2f; ",
  725. X                    prev_val->floatval);
  726. X                printf("current value %.2f.\n", v);
  727. X                line_ok = False;
  728. X            }
  729. X            break;
  730. X        case MAX_MIN:
  731. X            if (v > cf->fmt.max_min.max || v < cf->fmt.max_min.min) {
  732. X                if (line_ok) {
  733. X                    printf("%s has a ", cmd);
  734. X                    printf("max/min value out of range:\n");
  735. X                    printf("%s\n",line);
  736. X                }
  737. X                else {
  738. X                    printf("Also, it has a ");
  739. X                    printf("max/min value out of range:\n");
  740. X                }
  741. X                printf("where %s = %.2f; ", cf->name, v);
  742. X                printf("valid range %.2f to %.2f.\n",
  743. X                      cf->fmt.max_min.min, cf->fmt.max_min.max);
  744. X                line_ok = False;
  745. X            }
  746. X            break;
  747. X        case STRING:
  748. X            if (strncmp(cf->fmt.str_value, value, len) != 0) {
  749. X                if (line_ok) {
  750. X                    printf("%s has a string ", cmd);
  751. X                    printf("value which is not valid:\n");
  752. X                    printf("%s\n",line);
  753. X                }
  754. X                else {
  755. X                    printf("Also, it has a string");
  756. X                    printf("value which is not valid:\n");
  757. X                }
  758. X                printf("where %s = '%s'; Should be '%s'\n",
  759. X                    cf->name, value, cf->fmt.str_value);
  760. X                line_ok = False;
  761. X            }
  762. X            break;
  763. X        default:
  764. X            printf("check_item: impossible condition\n");
  765. X            break;
  766. X    }
  767. X    cmd_ok = line_ok;
  768. X}
  769. END_OF_check_item.c
  770. if test 2976 -ne `wc -c <check_item.c`; then
  771.     echo shar: \"check_item.c\" unpacked with wrong size!
  772. fi
  773. # end of overwriting check
  774. fi
  775. if test -f checkline.c -a "${1}" != "-c" ; then 
  776.   echo shar: Will not over-write existing file \"checkline.c\"
  777. else
  778. echo shar: Extracting \"checkline.c\" \(1962 characters\)
  779. sed "s/^X//" >checkline.c <<'END_OF_checkline.c'
  780. X/*
  781. X   checkline: check the input line just read in against what we expect
  782. X   to find and report any problems.  Actually, most of the work is done
  783. X   by check_item.  We just identify what needs to be checked.
  784. X
  785. X   Kenneth Ingham
  786. X
  787. X   Copyright (C) 1987 The University of New Mexico
  788. X*/
  789. X
  790. X#include "defs.h"
  791. X
  792. Xcheckline(cmd, line, prev_res)
  793. Xstruct cmd_st *cmd;
  794. Xchar *line;
  795. Xstruct old_cmd_st *prev_res;
  796. X{
  797. X    extern int line_ok;
  798. X    extern FILE *hf;
  799. X    struct change_fmt_st *cf;
  800. X    union out_fmt_u of;
  801. X    union all_u *prev_value;
  802. X    char value[MAX_STR];
  803. X    char key_val[MAX_STR];
  804. X    char *cmd_name;
  805. X
  806. X    cmd_name = (cmd->alias != NULL ? cmd->alias : cmd->pipeline);
  807. X        
  808. X    save_key(cmd, line, key_val); /* side effect: return key value */
  809. X    /* for each change format item */
  810. X    line_ok = True;
  811. X    for (cf=cmd->change_fmt; cf; cf=cf->next) {
  812. X        /* find the output format entry for this item */
  813. X        if (!find_of(cmd->out_type, cf->name, cmd->out_fmt, &of)) {
  814. X            fprintf(stderr, "Warning: %s appears in change list ",
  815. X                cf->name);
  816. X            fprintf(stderr, "but not in output format for %s\n",
  817. X                cmd_name);
  818. X            continue;
  819. X        }
  820. X
  821. X        /*
  822. X           find the part of the line corresponding to check.
  823. X           Also find the previous results corresponding to the
  824. X           key for this line (if any).
  825. X        */
  826. X        switch (cmd->out_type) {
  827. X        case RELATIVE:
  828. X            find_prev_value(prev_res, of.rel_fmt->name,
  829. X                key_val, &prev_value);
  830. X            if (get_rel_field(line, of.rel_fmt->field, value) !=
  831. X                NULL)
  832. X                check_item(cf, value, cmd_name, line,
  833. X                    prev_value);
  834. X            break;
  835. X        case COLUMN:
  836. X            find_prev_value(prev_res, of.rel_fmt->name,
  837. X                key_val, &prev_value);
  838. X            if (get_col_field(line, of.col_fmt->start, of.col_fmt->end, value) != NULL)
  839. X                check_item(cf, value, cmd_name, line,
  840. X                    prev_value);
  841. X            break;
  842. X        }
  843. X
  844. X        /*
  845. X           save the value in the history file for future
  846. X           comparisons.
  847. X        */
  848. X        if (cmd->key.rel_fmt != NULL)
  849. X            fprintf(hf, "\t\t%s %c %s\n", cf->name, 
  850. X                TCHAR(cf->type), value);
  851. X    }
  852. X    if (!line_ok)
  853. X        printf("---------\n");
  854. X}
  855. END_OF_checkline.c
  856. if test 1962 -ne `wc -c <checkline.c`; then
  857.     echo shar: \"checkline.c\" unpacked with wrong size!
  858. fi
  859. # end of overwriting check
  860. fi
  861. if test -f clean_hist.c -a "${1}" != "-c" ; then 
  862.   echo shar: Will not over-write existing file \"clean_hist.c\"
  863. else
  864. echo shar: Extracting \"clean_hist.c\" \(983 characters\)
  865. sed "s/^X//" >clean_hist.c <<'END_OF_clean_hist.c'
  866. X/*
  867. X   clean_hist: free up all memory used by the history structure.  The
  868. X   main purpose of this is to use the range checking of malloc to check
  869. X   for pointer problems.  If you don't have source, this is of dubious
  870. X   value.
  871. X
  872. X   Kenneth Ingham
  873. X
  874. X   Copyright (C) 1987 The University of New Mexico
  875. X*/
  876. X
  877. X#include "defs.h"
  878. X
  879. Xclean_hist()
  880. X{
  881. X    extern struct old_cmd_st *chead;
  882. X    struct old_cmd_st *bcp;
  883. X    struct val_st *vp, *bvp;
  884. X    struct key_st *kp, *bkp;
  885. X
  886. X    while (chead != NULL) {
  887. X        printf("freeing '%s'\n",chead->pipeline);
  888. X        free(chead->pipeline);
  889. X        kp = chead->keys;
  890. X        while (kp != NULL) {
  891. X            printf("\tfreeing '%s'\n",kp->key_value);
  892. X            free(kp->key_value);
  893. X            vp = kp->vals;
  894. X            while (vp != NULL) {
  895. X                printf("\tfreeing '%s'\n",kp->vals->name);
  896. X                free(vp->name);
  897. X                bvp = vp;
  898. X                vp = vp->next;
  899. X                free(bvp);
  900. X            }
  901. X            bkp = kp;
  902. X            kp = kp->next;
  903. X            free(bkp);
  904. X        }
  905. X        bcp = chead;
  906. X        chead = chead->next;
  907. X        free(bcp);
  908. X    }
  909. X    printf("\nThe world is now free again!  Aren't you glad?\n");
  910. X}
  911. END_OF_clean_hist.c
  912. if test 983 -ne `wc -c <clean_hist.c`; then
  913.     echo shar: \"clean_hist.c\" unpacked with wrong size!
  914. fi
  915. # end of overwriting check
  916. fi
  917. if test -f do_args.c -a "${1}" != "-c" ; then 
  918.   echo shar: Will not over-write existing file \"do_args.c\"
  919. else
  920. echo shar: Extracting \"do_args.c\" \(1260 characters\)
  921. sed "s/^X//" >do_args.c <<'END_OF_do_args.c'
  922. X/*
  923. X   do_args: parse the comand line arguments and set variables related to
  924. X   them.
  925. X
  926. X   Copied from main:
  927. X    watcher [-p] [-v] [-h histfile] [-f controlfile]
  928. X
  929. X    -p : pretty print control file as a verification of parse
  930. X        (default no pretty print).  This option prevents
  931. X        processing of control file.
  932. X    -v : be verbose.
  933. X    -h : file in which to save output for future compare (default
  934. X        ./watcher.history).
  935. X    -f : controlfile to use (default ./DEF_CONTROL{,2}).
  936. X
  937. X   Kenneth Ingham
  938. X
  939. X   Copyright (C) 1987 The University of New Mexico
  940. X*/
  941. X
  942. X#include "defs.h"
  943. X
  944. Xdo_args(argc, argv)
  945. Xint argc; 
  946. Xchar *argv[];
  947. X{
  948. X    extern int pflag, cflag, vflag;
  949. X    extern char controlname[], histfilename[];
  950. X
  951. X    register int i;
  952. X
  953. X    /* defaults */
  954. X    pflag = False;
  955. X    cflag = False;
  956. X    vflag = False;
  957. X    (void) sprintf(histfilename, "%s", DEF_HISTFILE);
  958. X
  959. X    for (i=1; i<argc; i++) {
  960. X        if (argv[i][0] == '-') {
  961. X            switch(argv[i][1]) {
  962. X            case 'v':
  963. X                vflag = True;
  964. X                break;
  965. X            case 'p':
  966. X                pflag = True;
  967. X                break;
  968. X            case 'h':
  969. X                i = getargv(histfilename, argv, i,
  970. X                    "history file name");
  971. X                break;
  972. X            case 'f':
  973. X                i = getargv(controlname, argv, i,
  974. X                    "controlfile name");
  975. X                cflag = True;
  976. X                break;
  977. X            default:
  978. X                fprintf(stderr, "Unknown flag '%s'\n", argv[i]);
  979. X                exit(1);
  980. X            }
  981. X        }
  982. X    }
  983. X}
  984. END_OF_do_args.c
  985. if test 1260 -ne `wc -c <do_args.c`; then
  986.     echo shar: \"do_args.c\" unpacked with wrong size!
  987. fi
  988. # end of overwriting check
  989. fi
  990. if test -f doit.c -a "${1}" != "-c" ; then 
  991.   echo shar: Will not over-write existing file \"doit.c\"
  992. else
  993. echo shar: Extracting \"doit.c\" \(1048 characters\)
  994. sed "s/^X//" >doit.c <<'END_OF_doit.c'
  995. X/*
  996. X   doit: here is where the real purpose of the program is actually
  997. X   carried out.  
  998. X
  999. X    for each command, run it and look for problems.
  1000. X    write results from this run back out.
  1001. X
  1002. X   need to change from popen to ps_open.
  1003. X
  1004. X   Kenneth Ingham
  1005. X
  1006. X   Copyright (C) 1987 The University of New Mexico
  1007. X*/
  1008. X
  1009. X#include "defs.h"
  1010. X
  1011. Xdoit()
  1012. X{
  1013. X    extern struct cmd_st *clist;
  1014. X    extern int vflag;
  1015. X    extern int cmd_ok;
  1016. X    extern FILE *hf;
  1017. X
  1018. X    char line[MAX_STR];
  1019. X    struct cmd_st *p;
  1020. X    struct old_cmd_st *prev_results, *find_prev_cmd();
  1021. X    FILE *ps, *popen();
  1022. X
  1023. X    /* run commands */
  1024. X    for (p=clist; p != NULL; p=p->next) {
  1025. X        cmd_ok = True;
  1026. X        if (vflag)
  1027. X            printf("Executing: '%s'\n\n", p->pipeline);
  1028. X        if (p->key.rel_fmt != NULL)
  1029. X            fprintf(hf, "%s\n", p->pipeline);
  1030. X        /* get prev results for comparison */
  1031. X        prev_results = find_prev_cmd(p->pipeline);
  1032. X        ps = popen(p->pipeline, "r");
  1033. X        while (fgets(line, MAX_STR, ps) != NULL) {
  1034. X            line[strlen(line)-1] = '\0';
  1035. X            if (vflag)
  1036. X                printf("  Read: '%s'\n",line);
  1037. X            checkline(p, line, prev_results);
  1038. X        }
  1039. X        if (!cmd_ok)
  1040. X            printf("\n");
  1041. X    }
  1042. X}
  1043. END_OF_doit.c
  1044. if test 1048 -ne `wc -c <doit.c`; then
  1045.     echo shar: \"doit.c\" unpacked with wrong size!
  1046. fi
  1047. # end of overwriting check
  1048. fi
  1049. if test -f externs.c -a "${1}" != "-c" ; then 
  1050.   echo shar: Will not over-write existing file \"externs.c\"
  1051. else
  1052. echo shar: Extracting \"externs.c\" \(429 characters\)
  1053. sed "s/^X//" >externs.c <<'END_OF_externs.c'
  1054. X/*
  1055. X   externs: external variable declarations.
  1056. X
  1057. X   Kenneth Ingham
  1058. X
  1059. X   Copyright (C) 1987 The University of New Mexico
  1060. X*/
  1061. X
  1062. X#include "defs.h"
  1063. X
  1064. XFILE *cf, *hf;
  1065. X
  1066. Xint intval, ointval;
  1067. Xchar *strval, ostrval[MAX_STR];
  1068. Xchar pipeline[MAX_STR];
  1069. X
  1070. Xstruct cmd_st *clist = NULL;
  1071. Xstruct old_cmd_st *chead = NULL;
  1072. X
  1073. Xint parse_error = False;
  1074. X
  1075. Xint pflag, cflag, vflag;
  1076. Xchar histfilename[MAX_STR];
  1077. Xchar controlname[MAX_STR];
  1078. Xint line_ok;
  1079. Xint cmd_ok;
  1080. END_OF_externs.c
  1081. if test 429 -ne `wc -c <externs.c`; then
  1082.     echo shar: \"externs.c\" unpacked with wrong size!
  1083. fi
  1084. # end of overwriting check
  1085. fi
  1086. if test -f find_of.c -a "${1}" != "-c" ; then 
  1087.   echo shar: Will not over-write existing file \"find_of.c\"
  1088. else
  1089. echo shar: Extracting \"find_of.c\" \(749 characters\)
  1090. sed "s/^X//" >find_of.c <<'END_OF_find_of.c'
  1091. X/*
  1092. X   find_of: find the output format corresponding for the field whose
  1093. X   name we are given.
  1094. X
  1095. X   Kenneth Ingham
  1096. X
  1097. X   Copyright (C) 1987 The University of New Mexico
  1098. X*/
  1099. X
  1100. X#include "defs.h"
  1101. X
  1102. Xfind_of(type, name, of_head, of)
  1103. Xint type;
  1104. Xunion out_fmt_u of_head, *of;
  1105. Xchar *name;
  1106. X{
  1107. X    struct rel_out_st *rf;
  1108. X    struct col_out_st *cf;
  1109. X
  1110. X    switch(type) {
  1111. X    case RELATIVE:
  1112. X        for (rf=of_head.rel_fmt; rf; rf=rf->next)
  1113. X            if (strcmp(name, rf->name) == 0) {
  1114. X                (*of).rel_fmt = rf;
  1115. X                return True;
  1116. X            }
  1117. X        break;
  1118. X    case COLUMN:
  1119. X        for (cf=of_head.col_fmt; cf; cf=cf->next)
  1120. X            if (strcmp(name, cf->name) == 0) {
  1121. X                (*of).col_fmt = cf;
  1122. X                return True;
  1123. X            }
  1124. X        break;
  1125. X    default:
  1126. X        fprintf(stderr,"internal error; unknown type in find_of\n");
  1127. X        exit(1);
  1128. X    }
  1129. X
  1130. X    return False;
  1131. X}
  1132. END_OF_find_of.c
  1133. if test 749 -ne `wc -c <find_of.c`; then
  1134.     echo shar: \"find_of.c\" unpacked with wrong size!
  1135. fi
  1136. # end of overwriting check
  1137. fi
  1138. if test -f find_pre_cmd.c -a "${1}" != "-c" ; then 
  1139.   echo shar: Will not over-write existing file \"find_pre_cmd.c\"
  1140. else
  1141. echo shar: Extracting \"find_pre_cmd.c\" \(441 characters\)
  1142. sed "s/^X//" >find_pre_cmd.c <<'END_OF_find_pre_cmd.c'
  1143. X/*
  1144. X   find_prev_cmd: find the previous results for this command (if any).  If
  1145. X   there is no match, then we return NULL.
  1146. X
  1147. X   Kenneth Ingham
  1148. X
  1149. X   Copyright (C) 1987 The University of New Mexico
  1150. X*/
  1151. X
  1152. X#include "defs.h"
  1153. X
  1154. Xstruct old_cmd_st *
  1155. Xfind_prev_cmd(pipeline)
  1156. Xchar *pipeline;
  1157. X{
  1158. X    extern struct old_cmd_st *chead;
  1159. X    struct old_cmd_st *cp;
  1160. X
  1161. X    cp = chead;
  1162. X    while (cp != NULL && strcmp(pipeline, cp->pipeline) != 0)
  1163. X        cp = cp->next;
  1164. X    
  1165. X    return cp;
  1166. X}
  1167. END_OF_find_pre_cmd.c
  1168. if test 441 -ne `wc -c <find_pre_cmd.c`; then
  1169.     echo shar: \"find_pre_cmd.c\" unpacked with wrong size!
  1170. fi
  1171. # end of overwriting check
  1172. fi
  1173. if test -f find_pre_val.c -a "${1}" != "-c" ; then 
  1174.   echo shar: Will not over-write existing file \"find_pre_val.c\"
  1175. else
  1176. echo shar: Extracting \"find_pre_val.c\" \(904 characters\)
  1177. sed "s/^X//" >find_pre_val.c <<'END_OF_find_pre_val.c'
  1178. X/*
  1179. X   find_prev_value: given an old command structure, look through the
  1180. X   prior output for the output for name of type type.  Return it in the
  1181. X   union pointed to by value or NULL if not found.
  1182. X
  1183. X   Kenneth Ingham
  1184. X
  1185. X   Copyright (C) 1987 The University of New Mexico
  1186. X*/
  1187. X
  1188. X#include "defs.h"
  1189. X
  1190. Xfind_prev_value(cmd, field_name, key_val, value)
  1191. Xstruct old_cmd_st *cmd;
  1192. Xchar *field_name, *key_val;
  1193. Xunion all_u **value;
  1194. X{
  1195. X    struct val_st *vp;
  1196. X    struct key_st *kp;
  1197. X
  1198. X    *value = NULL;
  1199. X
  1200. X    if (cmd == NULL)
  1201. X        return;
  1202. X    if (cmd->keys == NULL)
  1203. X        return;
  1204. X
  1205. X    /* find the correct keyword */
  1206. X    for (kp=cmd->keys; kp != NULL; kp=kp->next) {
  1207. X        if (strcmp(kp->key_value, key_val) == 0)
  1208. X            break;
  1209. X    }
  1210. X
  1211. X    if (kp == NULL)
  1212. X        return;
  1213. X    if (kp->vals == NULL)
  1214. X        return;
  1215. X
  1216. X    /* find the value under the keyword */
  1217. X    for (vp=kp->vals; vp != NULL; vp=vp->next) {
  1218. X        if (strcmp(vp->name, field_name) == 0) {
  1219. X            *value = &(vp->val);
  1220. X            return;
  1221. X        }
  1222. X    }
  1223. X}
  1224. END_OF_find_pre_val.c
  1225. if test 904 -ne `wc -c <find_pre_val.c`; then
  1226.     echo shar: \"find_pre_val.c\" unpacked with wrong size!
  1227. fi
  1228. # end of overwriting check
  1229. fi
  1230. if test -f get_col_fld.c -a "${1}" != "-c" ; then 
  1231.   echo shar: Will not over-write existing file \"get_col_fld.c\"
  1232. else
  1233. echo shar: Extracting \"get_col_fld.c\" \(787 characters\)
  1234. sed "s/^X//" >get_col_fld.c <<'END_OF_get_col_fld.c'
  1235. X/*
  1236. X   get_col_field: we have a column output format and want a certain
  1237. X   part of it.  Place the it in 'value' if it exists and return a
  1238. X   pointer to the string.  If there are problems place a null terminated
  1239. X   zero length string in 'value' and return NULL as an error condition.
  1240. X
  1241. X   Kenneth Ingham
  1242. X
  1243. X   Copyright (C) 1987 The University of New Mexico
  1244. X*/
  1245. X
  1246. X#include "defs.h"
  1247. X
  1248. Xchar *
  1249. Xget_col_field(line, start, end, value)
  1250. Xchar *line, *value;
  1251. Xint start, end;
  1252. X{
  1253. X    int len;
  1254. X
  1255. X    value[0] = '\0';
  1256. X    len = strlen(line);
  1257. X
  1258. X    /* error checking */
  1259. X    if (start > len || end > len) {
  1260. X        fprintf(stderr,"'%s' has %d columns. Specified were %d to %d\n",
  1261. X            line, len, start, start);
  1262. X        return NULL;
  1263. X    }
  1264. X    len = end - start + 1;
  1265. X    (void) strncpy(value, &line[start-1], len);
  1266. X    value[len] = '\0';
  1267. X
  1268. X    return value;
  1269. X}
  1270. END_OF_get_col_fld.c
  1271. if test 787 -ne `wc -c <get_col_fld.c`; then
  1272.     echo shar: \"get_col_fld.c\" unpacked with wrong size!
  1273. fi
  1274. # end of overwriting check
  1275. fi
  1276. if test -f get_rel_fld.c -a "${1}" != "-c" ; then 
  1277.   echo shar: Will not over-write existing file \"get_rel_fld.c\"
  1278. else
  1279. echo shar: Extracting \"get_rel_fld.c\" \(945 characters\)
  1280. sed "s/^X//" >get_rel_fld.c <<'END_OF_get_rel_fld.c'
  1281. X/*
  1282. X   get_rel_field: we have a relative output format and want a certain
  1283. X   field from it.  Place the field in 'value' if it exists and return a
  1284. X   pointer to the string.  If there are problems place a null terminated
  1285. X   zero length string in 'value' and return NULL as an error condition.
  1286. X
  1287. X   Kenneth Ingham
  1288. X
  1289. X   Copyright (C) 1987 The University of New Mexico
  1290. X*/
  1291. X
  1292. X#include "defs.h"
  1293. X
  1294. Xchar *
  1295. Xget_rel_field(line, field, value)
  1296. Xchar *line, *value;
  1297. Xint field;
  1298. X{
  1299. X    int i;
  1300. X    int nfields;
  1301. X    char *vec[MAX_VEC];
  1302. X
  1303. X    value[0] = '\0';
  1304. X
  1305. X    /* break up the line */
  1306. X    nfields = line_to_vec(line, vec, " \t");
  1307. X
  1308. X    /* error checking */
  1309. X    if (nfields <= 0) {
  1310. X        fprintf(stderr, "'%s' didn't break up into fields.\n",line);
  1311. X        return NULL;
  1312. X    }
  1313. X    if (nfields < field) {
  1314. X        fprintf(stderr, "Warning: '%s' has only %d fields, not %d\n",
  1315. X            line, nfields, field);
  1316. X        return NULL;
  1317. X    }
  1318. X
  1319. X    (void) strcpy(value, vec[field-1]);
  1320. X
  1321. X    for (i=0; i<nfields; i++)
  1322. X        free(vec[i]);
  1323. X
  1324. X    return value;
  1325. X}
  1326. END_OF_get_rel_fld.c
  1327. if test 945 -ne `wc -c <get_rel_fld.c`; then
  1328.     echo shar: \"get_rel_fld.c\" unpacked with wrong size!
  1329. fi
  1330. # end of overwriting check
  1331. fi
  1332. if test -f getargv.c -a "${1}" != "-c" ; then 
  1333.   echo shar: Will not over-write existing file \"getargv.c\"
  1334. else
  1335. echo shar: Extracting \"getargv.c\" \(495 characters\)
  1336. sed "s/^X//" >getargv.c <<'END_OF_getargv.c'
  1337. X/*
  1338. X   getargv: get a value from argv, whether it is immediately following
  1339. X   the flag or is the next argument.  Complain if not found and exit.
  1340. X
  1341. X   Kenneth Ingham
  1342. X
  1343. X   Copyright (C) 1987 The University of New Mexico
  1344. X*/
  1345. X
  1346. X#include "defs.h"
  1347. X
  1348. Xgetargv(what, argv, i, err)
  1349. Xchar *what, *argv[], *err;
  1350. Xint i;
  1351. X{
  1352. X    if (argv[i][2])
  1353. X        (void) strcpy(what, &argv[i][2]);
  1354. X    else {
  1355. X        if (argv[++i])
  1356. X            (void) strcpy(what, argv[i]);
  1357. X        else {
  1358. X            fprintf(stderr,"Missing %s!\n", err);
  1359. X            exit(1);
  1360. X        }
  1361. X    }
  1362. X    return i;
  1363. X}
  1364. END_OF_getargv.c
  1365. if test 495 -ne `wc -c <getargv.c`; then
  1366.     echo shar: \"getargv.c\" unpacked with wrong size!
  1367. fi
  1368. # end of overwriting check
  1369. fi
  1370. if test -f init.c -a "${1}" != "-c" ; then 
  1371.   echo shar: Will not over-write existing file \"init.c\"
  1372. else
  1373. echo shar: Extracting \"init.c\" \(296 characters\)
  1374. sed "s/^X//" >init.c <<'END_OF_init.c'
  1375. X/*
  1376. X   init: initialize any variables needing values, do any other
  1377. X   initialization needed.
  1378. X
  1379. X   Kenneth Ingham
  1380. X
  1381. X   Copyright (C) 1987 The University of New Mexico
  1382. X*/
  1383. X
  1384. X#include "defs.h"
  1385. X
  1386. Xinit()
  1387. X{
  1388. X    extern char ostrval[], *strval;
  1389. X
  1390. X    ostrval[0] = '\0';
  1391. X    strval = ostrval;
  1392. X    init_sigs();
  1393. X    open_cf();
  1394. X}
  1395. END_OF_init.c
  1396. if test 296 -ne `wc -c <init.c`; then
  1397.     echo shar: \"init.c\" unpacked with wrong size!
  1398. fi
  1399. # end of overwriting check
  1400. fi
  1401. if test -f init_sigs.c -a "${1}" != "-c" ; then 
  1402.   echo shar: Will not over-write existing file \"init_sigs.c\"
  1403. else
  1404. echo shar: Extracting \"init_sigs.c\" \(507 characters\)
  1405. sed "s/^X//" >init_sigs.c <<'END_OF_init_sigs.c'
  1406. X/*
  1407. X   init_sigs: take care of setting up the signal handling.
  1408. X
  1409. X   Kenneth Ingham
  1410. X
  1411. X   Copyright (C) 1987 The University of New Mexico
  1412. X*/
  1413. X
  1414. X#include "defs.h"
  1415. X
  1416. Xinit_sigs()
  1417. X{
  1418. X    int exit(), baderr();
  1419. X
  1420. X    (void) signal(SIGINT,  exit);
  1421. X    (void) signal(SIGHUP,  exit);
  1422. X    (void) signal(SIGQUIT, baderr);
  1423. X    (void) signal(SIGSEGV, baderr);
  1424. X    (void) signal(SIGBUS,  baderr);
  1425. X    (void) signal(SIGFPE,  baderr);
  1426. X    (void) signal(SIGILL,  baderr);
  1427. X#ifdef BSD
  1428. X    (void) signal(SIGTTIN, baderr);
  1429. X    (void) signal(SIGTTOU, baderr);
  1430. X#endif
  1431. X}
  1432. END_OF_init_sigs.c
  1433. if test 507 -ne `wc -c <init_sigs.c`; then
  1434.     echo shar: \"init_sigs.c\" unpacked with wrong size!
  1435. fi
  1436. # end of overwriting check
  1437. fi
  1438. if test -f line_to_vec.c -a "${1}" != "-c" ; then 
  1439.   echo shar: Will not over-write existing file \"line_to_vec.c\"
  1440. else
  1441. echo shar: Extracting \"line_to_vec.c\" \(1705 characters\)
  1442. sed "s/^X//" >line_to_vec.c <<'END_OF_line_to_vec.c'
  1443. X/*
  1444. X   line_to_vec: take a string and separate it into a vector of strings,
  1445. X    splitting it at characters which are supplied in 'splits'.
  1446. X    Ignore any 'splits' at the beginning.  Multiple 'splits' are
  1447. X    condensed into one.  Splits are discarded.
  1448. X
  1449. X   Assumptions:
  1450. X    line is null terminated.  
  1451. X    no single word is longer than MAX_STR.
  1452. X
  1453. X   Arguments:
  1454. X    line: line to split.
  1455. X    vec: split line.
  1456. X    splits: array of characters on which to split.  Null terminated.
  1457. X
  1458. X   Global data used:
  1459. X    none.
  1460. X   
  1461. X   Local variables:
  1462. X    len: length of 'word' so far.
  1463. X    name: current entry in the vector we are building.
  1464. X    word: pointer into name.
  1465. X
  1466. X   Returns:
  1467. X    The number of vectors created; -1 if malloc fails.
  1468. X    The argument vec is left with a NULL pointer after the last word.
  1469. X
  1470. X   Author:
  1471. X    Kenneth Ingham
  1472. X
  1473. X   Date:
  1474. X    Thu Sep  5 13:59:21 MDT 1985
  1475. X
  1476. X   Copyright (C) 1987 The University of New Mexico
  1477. X*/
  1478. X
  1479. X#include "defs.h"
  1480. X
  1481. Xline_to_vec(line, vec, splits)
  1482. Xchar *line, *vec[], *splits;
  1483. X{
  1484. X    register int i, v, j;
  1485. X    register unsigned len;
  1486. X    int n;
  1487. X    char word[MAX_STR];
  1488. X
  1489. X    if (line == NULL || line[0] == '\0')
  1490. X        return 0;
  1491. X    
  1492. X    /* skip any splits in the beginning */
  1493. X    for (i=0; line[i] && index(splits, line[i]) != 0; i++)
  1494. X        ;
  1495. X    
  1496. X    j = 0;
  1497. X    len = 0;
  1498. X    v = 0;
  1499. X    n = 0;
  1500. X    while (line[i]) {
  1501. X        if (index(splits, line[i]) != 0) {
  1502. X            word[j] = '\0';
  1503. X            vec[v] = malloc(len+1);
  1504. X            if (vec[v] == NULL)
  1505. X                return -1;
  1506. X            strcpy(vec[v], word);
  1507. X            j = 0;
  1508. X            len = 0;
  1509. X            v++;
  1510. X            n++;
  1511. X            i++;
  1512. X            for ( ; line[i] && index(splits, line[i]) != 0; i++)
  1513. X                ;
  1514. X        }
  1515. X        else {
  1516. X            word[j++] = line[i++];
  1517. X            len++;
  1518. X        }
  1519. X    }
  1520. X
  1521. X    if (index(splits, line[i]) != 0) {
  1522. X        word[j] = '\0';
  1523. X        vec[v] = malloc(len+1);
  1524. X        if (vec[v] == NULL)
  1525. X            return -1;
  1526. X        strcpy(vec[v], word);
  1527. X        n++;
  1528. X    }
  1529. X
  1530. X    return n;
  1531. X}
  1532. END_OF_line_to_vec.c
  1533. if test 1705 -ne `wc -c <line_to_vec.c`; then
  1534.     echo shar: \"line_to_vec.c\" unpacked with wrong size!
  1535. fi
  1536. # end of overwriting check
  1537. fi
  1538. if test -f main.c -a "${1}" != "-c" ; then 
  1539.   echo shar: Will not over-write existing file \"main.c\"
  1540. else
  1541. echo shar: Extracting \"main.c\" \(2114 characters\)
  1542. sed "s/^X//" >main.c <<'END_OF_main.c'
  1543. X/*
  1544. X   main: main routine for the watcher program.
  1545. X
  1546. X   read from a file describing commands (pipelines) to execute, formats of
  1547. X       the output, max changes allowed (% or absolute), and max & min
  1548. X       values for various fields.
  1549. X   problems noticed are reported.
  1550. X   as a side effect, be able to pretty print the description file
  1551. X       (originally use to verify parsing).
  1552. X   
  1553. X   format:
  1554. X   (command)\tformat :
  1555. X   \tfield\tchange\tmax\tmin
  1556. X       .
  1557. X       .
  1558. X       .
  1559. X
  1560. X   See yacc file for complete grammar description of control file.
  1561. X
  1562. X   outline of program:
  1563. X    parse control file and build data structures.
  1564. X    run each pipeline and compare output to previous output (only
  1565. X        save relevant fields; save directory is either default
  1566. X        or command line specified; no previous file or format
  1567. X        changed (ie we are watching different or new fields) we
  1568. X        create new file and next time we do compare).
  1569. X        differences that are not allowable are reported.
  1570. X    
  1571. X   Usage of program:
  1572. X    watcher [-p] [-v] [-h histfile] [-f controlfile]
  1573. X
  1574. X    -p : pretty print control file as a verification of parse
  1575. X        (default no pretty print).  This option prevents
  1576. X        processing of control file.
  1577. X    -v : be verbose when doing work; useful for debugging.
  1578. X    -h : file in which to save output for future compare (default
  1579. X        ./watcher.history).
  1580. X    -f : controlfile to use (default ./watcherfile or ./Watcherfile).
  1581. X
  1582. X   Note that the basic data structures are all linear linked lists, with
  1583. X   many items in the list being heads of other lists.  When problems
  1584. X   occur, get out the pencil and paper and start drawing the lists.  
  1585. X
  1586. X   Kenneth Ingham
  1587. X
  1588. X   Copyright (C) 1987 The University of New Mexico
  1589. X*/
  1590. X
  1591. X#include "defs.h"
  1592. X
  1593. Xmain(argc, argv)
  1594. Xint argc;
  1595. Xchar *argv[];
  1596. X{
  1597. X    extern int parse_error;
  1598. X    extern struct cmd_st *clist;
  1599. X    extern int pflag;
  1600. X
  1601. X    do_args(argc, argv);
  1602. X    init();
  1603. X
  1604. X    if (yyparse() == 1 || parse_error) {
  1605. X        fprintf(stderr, "%s: parse error in control file.\n", NAME);
  1606. X        exit(1);
  1607. X    }
  1608. X
  1609. X    if (clist == NULL) {
  1610. X        fprintf(stderr, "No command list to execute!\n");
  1611. X        exit(1);
  1612. X    }
  1613. X
  1614. X    if (pflag)
  1615. X        pp(clist);
  1616. X    else {
  1617. X        read_hist();
  1618. X        open_hf(); /* for writing our history */
  1619. X        doit();
  1620. X    }
  1621. X}
  1622. END_OF_main.c
  1623. if test 2114 -ne `wc -c <main.c`; then
  1624.     echo shar: \"main.c\" unpacked with wrong size!
  1625. fi
  1626. # end of overwriting check
  1627. fi
  1628. if test -f open_cf.c -a "${1}" != "-c" ; then 
  1629.   echo shar: Will not over-write existing file \"open_cf.c\"
  1630. else
  1631. echo shar: Extracting \"open_cf.c\" \(897 characters\)
  1632. sed "s/^X//" >open_cf.c <<'END_OF_open_cf.c'
  1633. X/*
  1634. X   open_cf: open the control file.  It is either specified on the
  1635. X   command line or DEF_CONTROL or DEF_CONTROL2.
  1636. X
  1637. X   Kenneth Ingham
  1638. X
  1639. X   Copyright (C) 1987 The University of New Mexico
  1640. X*/
  1641. X
  1642. X#include "defs.h"
  1643. X
  1644. Xopen_cf()
  1645. X{
  1646. X    extern char controlname[];
  1647. X    extern FILE *cf;
  1648. X    extern int cflag;
  1649. X
  1650. X    if (cflag) { /* specified control file */
  1651. X        cf = fopen(controlname, "r");
  1652. X        if (cf == NULL) {
  1653. X            fprintf(stderr, "Unable to open '%s'\n",
  1654. X                controlname);
  1655. X            exit(1);
  1656. X        }
  1657. X    }
  1658. X    else { /* try defaults */
  1659. X        if ((cf = fopen(DEF_CONTROL, "r")) == NULL) { /* #1 */
  1660. X            if ((cf = fopen(DEF_CONTROL2, "r")) == NULL) { /*#2*/
  1661. X                fprintf(stderr, "Unable to open %s or %s\n",
  1662. X                    DEF_CONTROL, DEF_CONTROL2);
  1663. X                exit(1);
  1664. X            }
  1665. X            /* if we're here #2 must have worked */
  1666. X            (void) strcpy(controlname, DEF_CONTROL2);
  1667. X        }
  1668. X        else
  1669. X            /* if we're here #1 must have worked */
  1670. X            (void) strcpy(controlname, DEF_CONTROL);
  1671. X    }
  1672. X}
  1673. END_OF_open_cf.c
  1674. if test 897 -ne `wc -c <open_cf.c`; then
  1675.     echo shar: \"open_cf.c\" unpacked with wrong size!
  1676. fi
  1677. # end of overwriting check
  1678. fi
  1679. if test -f open_hf.c -a "${1}" != "-c" ; then 
  1680.   echo shar: Will not over-write existing file \"open_hf.c\"
  1681. else
  1682. echo shar: Extracting \"open_hf.c\" \(373 characters\)
  1683. sed "s/^X//" >open_hf.c <<'END_OF_open_hf.c'
  1684. X/*
  1685. X   open_hf: open the history file for writing out log of what we looked
  1686. X   at this run.
  1687. X
  1688. X   Kenneth Ingham
  1689. X
  1690. X   Copyright (C) 1987 The University of New Mexico
  1691. X*/
  1692. X
  1693. X#include "defs.h"
  1694. X
  1695. Xopen_hf()
  1696. X{
  1697. X    extern char histfilename[];
  1698. X    extern FILE *hf;
  1699. X
  1700. X    hf = fopen(histfilename, "w");
  1701. X    if (hf == NULL) {
  1702. X        fprintf(stderr, "Unable to open '%s'\n",
  1703. X            histfilename);
  1704. X        exit(1);
  1705. X    }
  1706. X}
  1707. END_OF_open_hf.c
  1708. if test 373 -ne `wc -c <open_hf.c`; then
  1709.     echo shar: \"open_hf.c\" unpacked with wrong size!
  1710. fi
  1711. # end of overwriting check
  1712. fi
  1713. if test -f pp.c -a "${1}" != "-c" ; then 
  1714.   echo shar: Will not over-write existing file \"pp.c\"
  1715. else
  1716. echo shar: Extracting \"pp.c\" \(534 characters\)
  1717. sed "s/^X//" >pp.c <<'END_OF_pp.c'
  1718. X/*
  1719. X   pp: pretty print the command structure.
  1720. X
  1721. X   Kenneth Ingham
  1722. X
  1723. X   Copyright (C) 1987 The University of New Mexico
  1724. X*/
  1725. X
  1726. X#include "defs.h"
  1727. X
  1728. Xpp(clist)
  1729. Xstruct cmd_st *clist;
  1730. X{
  1731. X    extern char histfilename[];
  1732. X    extern char controlname[];
  1733. X
  1734. X    printf("History file name: %s\n", histfilename);
  1735. X    printf("Control file name: %s\n", controlname);
  1736. X    printf("\n\n");
  1737. X
  1738. X    while (clist != NULL) {
  1739. X        printf("( %s )\n", clist->pipeline);
  1740. X        pp_out(clist->out_type, clist->out_fmt);
  1741. X        printf(" :\n");
  1742. X        pp_change(clist->change_fmt);
  1743. X        clist = clist->next;
  1744. X    }
  1745. X}
  1746. END_OF_pp.c
  1747. if test 534 -ne `wc -c <pp.c`; then
  1748.     echo shar: \"pp.c\" unpacked with wrong size!
  1749. fi
  1750. # end of overwriting check
  1751. fi
  1752. if test -f pp_change.c -a "${1}" != "-c" ; then 
  1753.   echo shar: Will not over-write existing file \"pp_change.c\"
  1754. else
  1755. echo shar: Extracting \"pp_change.c\" \(813 characters\)
  1756. sed "s/^X//" >pp_change.c <<'END_OF_pp_change.c'
  1757. X/*
  1758. X   pp_change: pretty print the change format.
  1759. X
  1760. X   Kenneth Ingham
  1761. X
  1762. X   Copyright (C) 1987 The University of New Mexico
  1763. X*/
  1764. X
  1765. X#include "defs.h"
  1766. X
  1767. Xpp_change(cf)
  1768. Xstruct change_fmt_st *cf;
  1769. X{
  1770. X    while (cf != NULL) {
  1771. X        switch(cf->type) {
  1772. X            case PERCENT:
  1773. X                printf("\t\t%s %5.2f %%", cf->name,
  1774. X                    cf->fmt.percent*100);
  1775. X                break;
  1776. X            case ABSOLUTE:
  1777. X                printf("\t\t%s %6.2f", cf->name,
  1778. X                    cf->fmt.abs_amount);
  1779. X                break;
  1780. X            case MAX_MIN:
  1781. X                printf("\t\t%s %6.2f %6.2f", cf->name,
  1782. X                    cf->fmt.max_min.min,
  1783. X                    cf->fmt.max_min.max);
  1784. X                break;
  1785. X            case STRING:
  1786. X                printf("\t\t%s \"%s\"", cf->name,
  1787. X                    cf->fmt.str_value);
  1788. X                break;
  1789. X            default:
  1790. X                printf("Impossible change format type: %d\n",
  1791. X                    cf->type);
  1792. X                break;
  1793. X        }
  1794. X        if (cf->next != NULL)
  1795. X            printf(" ;\n");
  1796. X        else
  1797. X            printf(" .\n");
  1798. X        cf = cf->next;
  1799. X    }
  1800. X}
  1801. END_OF_pp_change.c
  1802. if test 813 -ne `wc -c <pp_change.c`; then
  1803.     echo shar: \"pp_change.c\" unpacked with wrong size!
  1804. fi
  1805. # end of overwriting check
  1806. fi
  1807. if test -f pp_out.c -a "${1}" != "-c" ; then 
  1808.   echo shar: Will not over-write existing file \"pp_out.c\"
  1809. else
  1810. echo shar: Extracting \"pp_out.c\" \(696 characters\)
  1811. sed "s/^X//" >pp_out.c <<'END_OF_pp_out.c'
  1812. X/*
  1813. X   pp_out: pretty print the output of command structure.
  1814. X
  1815. X   Kenneth Ingham
  1816. X
  1817. X   Copyright (C) 1987 The University of New Mexico
  1818. X*/
  1819. X
  1820. X#include "defs.h"
  1821. X
  1822. Xpp_out(type,of)
  1823. Xint type;
  1824. Xunion out_fmt_u of;
  1825. X{
  1826. X    struct rel_out_st *rp;
  1827. X    struct col_out_st *cp;
  1828. X
  1829. X    switch(type) {
  1830. X        case RELATIVE:
  1831. X            rp = of.rel_fmt;
  1832. X            while (rp != NULL) {
  1833. X                printf(" %d %s %% %c", rp->field, rp->name,
  1834. X                    TCHAR(rp->type));
  1835. X                rp = rp->next;
  1836. X            }
  1837. X            break;
  1838. X        case COLUMN:
  1839. X            cp = of.col_fmt;
  1840. X            while (cp != NULL) {
  1841. X                printf(" %d - %d %s %% %c", cp->start,
  1842. X                    cp->end, cp->name, TCHAR(cp->type));
  1843. X                cp = cp->next;
  1844. X            }
  1845. X            break;
  1846. X        default:
  1847. X            printf("Impossible value for outfmt type: %d\n", type);
  1848. X            break;
  1849. X    }
  1850. X}
  1851. END_OF_pp_out.c
  1852. if test 696 -ne `wc -c <pp_out.c`; then
  1853.     echo shar: \"pp_out.c\" unpacked with wrong size!
  1854. fi
  1855. # end of overwriting check
  1856. fi
  1857. if test -f read_hist.c -a "${1}" != "-c" ; then 
  1858.   echo shar: Will not over-write existing file \"read_hist.c\"
  1859. else
  1860. echo shar: Extracting \"read_hist.c\" \(3404 characters\)
  1861. sed "s/^X//" >read_hist.c <<'END_OF_read_hist.c'
  1862. X/*
  1863. X   read_hist: open the file containing the results of our last run.  If
  1864. X   it is not there then we assume that this is a first run and set the
  1865. X   head of the list to NULL.  Otherwise, we read the results of the previous
  1866. X   run into a mess of a data structure for later use in comparisons.
  1867. X
  1868. X   Assumed format of history file:
  1869. X
  1870. X   command
  1871. X    key
  1872. X        name type value
  1873. X
  1874. X   witht the following definitions:
  1875. X    command: pipeline that was executed
  1876. X    key: value of key on line
  1877. X    name: output field name
  1878. X    type: field type (same as defined in output format)
  1879. X    value: what was in the field.
  1880. X
  1881. X   We create a linked list of linked lists of linked lists.  Improvement
  1882. X   would be to change to a tree of some sort to speed up searches.
  1883. X
  1884. X   Kenneth Ingham
  1885. X
  1886. X   Copyright (C) 1987 The University of New Mexico
  1887. X*/
  1888. X
  1889. X#include "defs.h"
  1890. X
  1891. Xread_hist()
  1892. X{
  1893. X    extern char histfilename[];
  1894. X    extern FILE *hf;
  1895. X    extern int vflag;
  1896. X    extern struct old_cmd_st *chead;
  1897. X
  1898. X    char line[MAX_STR];
  1899. X    struct old_cmd_st *cp;
  1900. X    struct val_st *vp;
  1901. X    struct key_st *kp;
  1902. X    int len;
  1903. X    char *sp;
  1904. X
  1905. X    if (vflag)
  1906. X        printf("Using %s for historyfile\n", histfilename);
  1907. X
  1908. X    hf = fopen(histfilename, "r");
  1909. X    if (hf == NULL) {
  1910. X        if (vflag)
  1911. X            printf("This is a first run.\n");
  1912. X        chead = NULL;
  1913. X        return;
  1914. X    }
  1915. X
  1916. X    chead = NULL;  cp = NULL;  kp = NULL;
  1917. X    while (fgets(line, MAX_STR, hf) != NULL) {
  1918. X        line[strlen(line)-1] = '\0'; /* kill trailing cr */
  1919. X        if (line[0] != '\t') { /* command */
  1920. X            if (chead == NULL)  {
  1921. X                cp = (struct old_cmd_st *)malloc(sizeof(struct old_cmd_st));
  1922. X                chead = cp;
  1923. X            }
  1924. X            else {
  1925. X                cp->next = (struct old_cmd_st *)malloc(sizeof(struct old_cmd_st));
  1926. X                cp = cp->next;
  1927. X            }
  1928. X
  1929. X            cp->pipeline = malloc((unsigned)strlen(line)+1);
  1930. X            (void) strcpy(cp->pipeline, line);
  1931. X            cp->next = NULL;
  1932. X        }
  1933. X        else if (line[0] == '\t' && line[1] != '\t') { /* key */
  1934. X            if (cp == NULL) {
  1935. X                printf("Bad history file: keyword found ");
  1936. X                printf("before pipeline.  Ignoring history ");
  1937. X                printf("file.\n");
  1938. X                chead = NULL;
  1939. X                return;
  1940. X            }
  1941. X            if (cp->keys == NULL) {
  1942. X                cp->keys = (struct key_st *)malloc(sizeof(struct key_st));
  1943. X                kp = cp->keys;
  1944. X            }
  1945. X            else {
  1946. X                kp->next = (struct key_st *)malloc(sizeof(struct key_st));
  1947. X                kp = kp->next;
  1948. X            }
  1949. X            kp->next = NULL;
  1950. X            kp->key_value = malloc((unsigned)strlen(line)+1);
  1951. X            (void) strcpy(kp->key_value, &line[1]);
  1952. X        }
  1953. X        else if (line[0] == '\t' && line[1] == '\t') { /* vals */
  1954. X            if (kp == NULL) {
  1955. X                printf("Bad history file: value found ");
  1956. X                printf("before keyword.  Ignoring history ");
  1957. X                printf("file.\n");
  1958. X                chead = NULL;
  1959. X                return;
  1960. X            }
  1961. X            if (kp->vals == NULL) {
  1962. X                kp->vals = (struct val_st *)malloc(sizeof(struct val_st));
  1963. X                vp = kp->vals;
  1964. X            }
  1965. X            else {
  1966. X                vp->next = (struct val_st *)malloc(sizeof(struct val_st));
  1967. X                vp = vp->next;
  1968. X            }
  1969. X            vp->next = NULL;
  1970. X            sp = index(&line[2], ' ');
  1971. X            len = sp - &line[2];
  1972. X            vp->name = malloc((unsigned)len+1);
  1973. X            (void) strncpy(vp->name, &line[2], len);
  1974. X            vp->name[len] = '\0';
  1975. X            sp++;
  1976. X            len = strlen(line) - len;
  1977. X            switch (*sp) {
  1978. X                case 's':
  1979. X                    vp->val.strval = malloc((unsigned)len+1);
  1980. X                    (void) strcpy(vp->val.strval, sp+2);
  1981. X                    vp->type = STRING;
  1982. X                    break;
  1983. X                case 'd':
  1984. X                    vp->val.floatval = atof(sp+2);
  1985. X                    vp->type = FLOAT;
  1986. X                    break;
  1987. X                default:
  1988. X                    /* bad condition */
  1989. X                    printf("Unknown data type in history file.\n");
  1990. X                    printf("Offending line: %s\n",line);
  1991. X                    exit(1);
  1992. X                    break;
  1993. X            }
  1994. X        }
  1995. X    }
  1996. X    (void) fclose(hf);
  1997. X}
  1998. END_OF_read_hist.c
  1999. if test 3404 -ne `wc -c <read_hist.c`; then
  2000.     echo shar: \"read_hist.c\" unpacked with wrong size!
  2001. fi
  2002. # end of overwriting check
  2003. fi
  2004. if test -f save_key.c -a "${1}" != "-c" ; then 
  2005.   echo shar: Will not over-write existing file \"save_key.c\"
  2006. else
  2007. echo shar: Extracting \"save_key.c\" \(1239 characters\)
  2008. sed "s/^X//" >save_key.c <<'END_OF_save_key.c'
  2009. X/*
  2010. X   save_key: save the key for this line in the history file so that
  2011. X   we can use it next run.
  2012. X
  2013. X   Assume that the keyory file is opened and that the pipeline has
  2014. X   already been placed in the file.  We place the data in the file in
  2015. X   the following format:
  2016. X
  2017. X    pipeline
  2018. X        key_value
  2019. X            name value
  2020. X                .
  2021. X                .
  2022. X                .
  2023. X            .
  2024. X            .
  2025. X            .
  2026. X    pipeline
  2027. X       .
  2028. X       .
  2029. X       .
  2030. X   
  2031. X
  2032. X   Side effect: return the actual key value for other parts of the
  2033. X   program to use.
  2034. X
  2035. X   Kenneth Ingham
  2036. X
  2037. X   Copyright (C) 1987 The University of New Mexico
  2038. X*/
  2039. X
  2040. X#include "defs.h"
  2041. X
  2042. Xsave_key(cmd, line, key_val)
  2043. Xstruct cmd_st *cmd;
  2044. Xchar *line, *key_val;
  2045. X{
  2046. X    extern int vflag;
  2047. X    extern FILE *hf; /* assumed to be already open */
  2048. X
  2049. X    if (cmd->key.col_fmt == NULL) { /* no key; no reason to save. */
  2050. X        if (vflag) 
  2051. X            printf("%s has no key field.\n",cmd->pipeline);
  2052. X        return;
  2053. X    }
  2054. X
  2055. X    switch (cmd->out_type) {
  2056. X        case RELATIVE:
  2057. X            (void) get_rel_field(line, cmd->key.rel_fmt->field,
  2058. X                key_val);
  2059. X            break;
  2060. X        case COLUMN:
  2061. X            (void) get_col_field(line, cmd->key.col_fmt->start,
  2062. X                cmd->key.col_fmt->end, key_val);
  2063. X            break;
  2064. X    }
  2065. X            
  2066. X    if (!key_val[0]) {
  2067. X        if (vflag)
  2068. X            printf("the key field for %s is empty\n",cmd->pipeline);
  2069. X        return;
  2070. X    }
  2071. X    
  2072. X    fprintf(hf, "\t%s\n",key_val);
  2073. X}
  2074. END_OF_save_key.c
  2075. if test 1239 -ne `wc -c <save_key.c`; then
  2076.     echo shar: \"save_key.c\" unpacked with wrong size!
  2077. fi
  2078. # end of overwriting check
  2079. fi
  2080. if test -f yyerror.c -a "${1}" != "-c" ; then 
  2081.   echo shar: Will not over-write existing file \"yyerror.c\"
  2082. else
  2083. echo shar: Extracting \"yyerror.c\" \(138 characters\)
  2084. sed "s/^X//" >yyerror.c <<'END_OF_yyerror.c'
  2085. X/*
  2086. X   wow.
  2087. X
  2088. X   Copyright (C) 1987 The University of New Mexico
  2089. X*/
  2090. X
  2091. X#include "defs.h"
  2092. X
  2093. Xyyerror(s)
  2094. Xchar *s;
  2095. X{
  2096. X    fprintf(stderr,"%s\n", s);
  2097. X}
  2098. END_OF_yyerror.c
  2099. if test 138 -ne `wc -c <yyerror.c`; then
  2100.     echo shar: \"yyerror.c\" unpacked with wrong size!
  2101. fi
  2102. # end of overwriting check
  2103. fi
  2104. if test -f yylex.c -a "${1}" != "-c" ; then 
  2105.   echo shar: Will not over-write existing file \"yylex.c\"
  2106. else
  2107. echo shar: Extracting \"yylex.c\" \(1804 characters\)
  2108. sed "s/^X//" >yylex.c <<'END_OF_yylex.c'
  2109. X/*
  2110. X   yylex for watcher: this is a simple routine looking for numbers,
  2111. X   special characters and strings.  The special chars are stored in
  2112. X   'words' and represent tokens by themselves.   In y.tab.h are the
  2113. X   values to return for the various tokens which are not listed in
  2114. X   'words'.
  2115. X
  2116. X   Kenneth Ingham
  2117. X
  2118. X   Copyright (C) 1987 The University of New Mexico
  2119. X*/
  2120. X
  2121. X#include "defs.h"
  2122. X
  2123. Xchar words[] = "\".*|;:%@$-{}";
  2124. X
  2125. Xyylex()
  2126. X{
  2127. X    extern int yylval, intval, ointval;
  2128. X    extern char *strval, ostrval[], pipeline[];
  2129. X    extern FILE *cf;
  2130. X    int c, value, i;
  2131. X    static char str[MAX_STR];
  2132. X
  2133. X    while (isspace(c = getc(cf)))
  2134. X        ;
  2135. X
  2136. X    if (c == EOF)
  2137. X        return EOF;
  2138. X
  2139. X    if (c == '(') { /* aha, pipeline */
  2140. X        c = getc(cf);
  2141. X        for (i=0; c != EOF && c != ')'; i++) {
  2142. X            str[i] = c;
  2143. X            c = getc(cf);
  2144. X        }
  2145. X        str[i] = '\0';
  2146. X        if (c == EOF) {
  2147. X            fprintf(stderr, "Missing ')' to end pipeline.\n");
  2148. X            return EOF;
  2149. X        }
  2150. X        (void) strcpy(pipeline, str);
  2151. X        return PIPELINE;
  2152. X    }
  2153. X
  2154. X    if (c == '#') { /* comment to end of line */
  2155. X        while (c != '\n' && c != EOF)
  2156. X            c = getc(cf);
  2157. X        if (c == EOF)
  2158. X            return EOF;
  2159. X        return yylex();
  2160. X    }
  2161. X
  2162. X    if (index(words, c) != 0) {
  2163. X        yylval = c;
  2164. X        return c;
  2165. X    }
  2166. X
  2167. X    if (isdigit(c)) { /* a number */
  2168. X        value = c - '0';
  2169. X        while (isdigit(c = getc(cf)))
  2170. X            value = value * 10 + c - '0';
  2171. X        ointval = intval;
  2172. X        intval = value;
  2173. X        (void) ungetc(c, cf);
  2174. X        return NUMBER;
  2175. X    }
  2176. X
  2177. X    (void) strcpy(ostrval, strval);
  2178. X
  2179. X    if (c == '\'') { /* literal string */
  2180. X        c = getc(cf);
  2181. X        for (i=0; c != EOF && c != '\''; i++) {
  2182. X            str[i] = c;
  2183. X            c = getc(cf);
  2184. X        }
  2185. X        str[i] = '\0';
  2186. X        strval = str;
  2187. X        return STRING;
  2188. X    }
  2189. X
  2190. X    /* nothing else matched.  Must be plain string (whitespace sep) */
  2191. X    for (i=1, str[0]=c; c != EOF && !isspace(c) && !index(words,c); i++) {
  2192. X        c = getc(cf);
  2193. X        str[i] = c;
  2194. X    }
  2195. X    (void) ungetc(c, cf);
  2196. X    str[i-1] = '\0';
  2197. X    strval = str;
  2198. X    return STRING;
  2199. X}
  2200. END_OF_yylex.c
  2201. if test 1804 -ne `wc -c <yylex.c`; then
  2202.     echo shar: \"yylex.c\" unpacked with wrong size!
  2203. fi
  2204. # end of overwriting check
  2205. fi
  2206. echo shar: End of archive 1 \(of 2\).
  2207. cp /dev/null ark1isdone
  2208. MISSING=""
  2209. for I in 1 2 ; do
  2210.     if test ! -f ark${I}isdone ; then
  2211.     MISSING="${MISSING} ${I}"
  2212.     fi
  2213. done
  2214. if test "${MISSING}" = "" ; then
  2215.     echo You have unpacked both archives.
  2216.     rm -f ark[1-9]isdone
  2217. else
  2218.     echo You still need to unpack the following archives:
  2219.     echo "        " ${MISSING}
  2220. fi
  2221. ##  End of shell archive.
  2222. exit 0
  2223.